package com.chenfan.process.biz.impl;

import com.alibaba.fastjson.JSONObject;
import com.chenfan.ccp.common.exception.ApiException;
import com.chenfan.ccp.common.result.R;
import com.chenfan.ccp.entity.BaseEntity;
import com.chenfan.ccp.executor.SmartExecutorService;
import com.chenfan.ccp.util.tool.UuidUtil;
import com.chenfan.notify.NotifyClient;
import com.chenfan.notify.dto.NotifyTransferDTO;
import com.chenfan.process.biz.ApprovalTransferBiz;
import com.chenfan.process.common.exception.ProcessResultCode;
import com.chenfan.process.entity.dto.ApprovalDataTransferDTO;
import com.chenfan.process.entity.dto.ApprovalTemplateDTO;
import com.chenfan.process.entity.dto.InstanceSnapshotDTO;
import com.chenfan.process.entity.dto.RefreshDataDTO;
import com.chenfan.process.entity.po.*;
import com.chenfan.process.entity.vo.DataTransferVO;
import com.chenfan.process.entity.vo.TemplateVersionVO;
import com.chenfan.process.enums.TransferEnum;
import com.chenfan.process.enums.TransferTypeEnum;
import com.chenfan.process.service.*;
import com.chenfan.process.util.ConvertUtils;
import com.chenfan.process.util.NodeUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author liuming
 * @date 2021/10/18
 */
@Slf4j
@Service
public class ApprovalTransferBizImpl implements ApprovalTransferBiz {

    @Autowired
    private ProcessService processService;
    @Autowired
    private ApprovalService approvalService;
    @Autowired
    private ProcessRelatedService processRelatedService;
    @Autowired
    private ProcessDetailService processDetailService;
    @Autowired
    private ApprovalSnapshotPoService approvalSnapshotPoService;
    @Autowired
    private ProcessInstanceApproveService instanceApproveService;
    @Autowired
    private ProcessTransferLogService processTransferLogService;
    @Autowired
    private ApprovalTemplateService approvalTemplateService;
    @Autowired
    private ProcessRelatedAttributeService processRelatedAttributeService;
    @Autowired
    private ProcessFormNodeRelationService processFormNodeRelationService;
    @Autowired
    private TransferLogDetailService transferLogDetailService;
    @Autowired
    private ApprovalTemplateSnapshotService approvalTemplateSnapshotService;
    @Autowired
    private NotifyClient notifyClient;
    @Autowired
    private TemplateConfigService templateConfigService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approvalDataTransfer(ApprovalDataTransferDTO data) throws InterruptedException, ExecutionException {
        // todo liaoliang 待优化 数据量太多
        Map<Long, ProcessPo> processMap = processService.list().stream().collect(Collectors.toMap(BaseEntity::getId, e -> e));
        List<ApprovalDataTransferDTO.ApprovalDataTransferInternalDTO> templateDataList = data.getTemplateDataList();
        if (CollectionUtils.isEmpty(templateDataList)) {
            return;
        }
        List<Long> templateIdList = templateDataList.stream().map(ApprovalDataTransferDTO.ApprovalDataTransferInternalDTO::getApprovalTemplateId).collect(Collectors.toList());
        Map<Long, ApprovalDataTransferDTO.ApprovalDataTransferInternalDTO> dataMap = templateDataList.stream().collect(Collectors.toMap(ApprovalDataTransferDTO.ApprovalDataTransferInternalDTO::getApprovalTemplateId, e -> e));
        // 拿到模板数据
        Map<Long, ApprovalTemplatePo> approvalTemplateMap = approvalTemplateService.listByIds(templateIdList).stream().collect(Collectors.toMap(ApprovalTemplatePo::getId, e -> e, (e1, e2) -> e2));
        log.info("开始根据模板与转移人进行模板筛选...");
        // 找到对应的审批模板和版本
        Map<Long, List<TemplateVersionVO>> templateMap = getTemplate(templateIdList, data.getSourceUserId(), processMap);
        log.info("查询到审批模板和对应的版本数据:{}", JSONObject.toJSONString(templateMap));
        if (templateMap.isEmpty()) {
            // 没有数据需要转移
            throw new ApiException(ProcessResultCode.NO_DATA_TO_TRANSFER);
        }
        ExecutorService executorService = SmartExecutorService.newFixedThreadPool();
        ExecutorCompletionService<DataTransferVO> executorCompletionService = new ExecutorCompletionService<>(executorService);
        // 2. 根据审批模板查询出所有审批中的数据

        templateMap.forEach((k, v) -> executorCompletionService.submit(new Task(k, v, data, processMap, dataMap.get(k))));
        executorService.shutdown();
        ProcessTransferLogPo transferLog = ProcessTransferLogPo.ofDefault(data);

        // 3. 生成新的版本值,将原始的detail, instance的值更新
        Long totalCount = 0L;
        List<NotifyTransferDTO> notify = new ArrayList<>();
        List<TransferLogDetailPo> transferLogList = new ArrayList<>();
        for (Long template : templateMap.keySet()) {
            Future<DataTransferVO> take = executorCompletionService.take();
            DataTransferVO dataTransferVO = take.get();
            if (Objects.isNull(dataTransferVO)) {
                continue;
            }

            List<ApprovalPo> approvalPoList = dataTransferVO.getApprovalPoList();
            if (!CollectionUtils.isEmpty(approvalPoList)) {
                approvalService.updateBatchById(approvalPoList);
                totalCount += approvalPoList.size();

                List<NotifyTransferDTO> notifyList = approvalPoList.stream().map(e -> {
                    NotifyTransferDTO transferDTO = new NotifyTransferDTO();
                    transferDTO.setApprovalId(e.getApprovalId());
                    transferDTO.setSourceUserId(data.getSourceUserId());
                    transferDTO.setTargetUserId(data.getTargetUserId());
                    transferDTO.setTargetUserName(data.getTargetUserName());
                    return transferDTO;
                }).collect(Collectors.toList());
                notify.addAll(notifyList);
            }
            List<ProcessDetailPo> processDetailList = dataTransferVO.getProcessDetailList();
            if (!CollectionUtils.isEmpty(processDetailList)) {
                processDetailService.updateBatchById(processDetailList);
            }
            List<ProcessInstanceApprovePo> processInstanceApproveList = dataTransferVO.getProcessInstanceApproveList();
            if (!CollectionUtils.isEmpty(processInstanceApproveList)) {
                instanceApproveService.updateBatchById(processInstanceApproveList);
            }
            List<ApprovalSnapshotPo> snapshotList = dataTransferVO.getSnapshotList();
            if (!CollectionUtils.isEmpty(snapshotList)) {
                approvalSnapshotPoService.updateBatchById(snapshotList);
            }
            List<ProcessPo> saveProcessList = dataTransferVO.getSaveProcessList();
            if (!CollectionUtils.isEmpty(saveProcessList)) {
                processService.saveBatch(saveProcessList);
            }
            List<ProcessRelatedPo> relatedProcessList = dataTransferVO.getRelatedProcessList();
            if (!CollectionUtils.isEmpty(relatedProcessList)) {
                processRelatedService.saveBatch(relatedProcessList);
            }

            List<ProcessRelatedAttribute> addMoreRelationAttributes = dataTransferVO.getAddMoreRelationAttributes();
            if (!CollectionUtils.isEmpty(addMoreRelationAttributes)) {
                processRelatedAttributeService.saveBatch(addMoreRelationAttributes);
            }

            List<ProcessFormNodeRelation> processFormNodeRelations = dataTransferVO.getProcessFormNodeRelations();
            if (!CollectionUtils.isEmpty(processFormNodeRelations)) {
                processFormNodeRelationService.saveBatch(processFormNodeRelations);
            }

            ApprovalTemplatePo approvalTemplatePo = dataTransferVO.getApprovalTemplatePo();
            if (Objects.nonNull(approvalTemplatePo)) {
                approvalTemplateService.updateById(approvalTemplatePo);
            }

            TemplateConfigPo templateConfigPo = dataTransferVO.getTemplateConfigPo();
            if (Objects.nonNull(templateConfigPo)) {
                templateConfigService.save(templateConfigPo);
            }

            List<TransferLogDetailPo> transfer = dataTransferVO.getTransferLogList();
            if (!CollectionUtils.isEmpty(transfer)) {
                transferLogList.addAll(transfer);
            }
            ApprovalTemplateSnapshotPo approvalTemplateSnapshotPo = dataTransferVO.getApprovalTemplateSnapshotPo();
            if (Objects.nonNull(approvalTemplateSnapshotPo)) {
                approvalTemplateSnapshotService.save(approvalTemplateSnapshotPo);
            }

        }

        //todo liaoliang
        if (!CollectionUtils.isEmpty(notify)) {
            // 多线程异步发送到消息系统
            CompletableFuture.runAsync(() -> {
                log.info("异步处理待办数据:{}条", notify.size());
                R<Integer> transferResult = notifyClient.transferData(notify);
                log.info("Transfer Result: {}", JSONObject.toJSONString(transferResult));
            });
        }
        // 记录日志
        List<String> templateSet = templateIdList.stream().map(e -> {
            ApprovalTemplatePo approvalTemplatePo = approvalTemplateMap.getOrDefault(e, new ApprovalTemplatePo());
            return approvalTemplatePo.getTitle();
        }).filter(e -> !StringUtils.isEmpty(e)).collect(Collectors.toList());
        transferLog.setBusinessTemplate(JSONObject.toJSONString(templateSet));
        transferLog.setDataCount(totalCount);
        transferLog.setStatus(TransferEnum.SUCCESS.getCode());
        transferLog.setTransferType(data.getTransferType());
        processTransferLogService.save(transferLog);

        if (!CollectionUtils.isEmpty(transferLogList)) {
            transferLogList.forEach(e -> e.setTransferId(transferLog.getId()));
            transferLogDetailService.saveBatch(transferLogList);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void initData(List<Long> approvalTemplateIdList) throws ExecutionException, InterruptedException {
        if (CollectionUtils.isEmpty(approvalTemplateIdList)) {
            return;
        }
        // 查询所有的数据
        List<ApprovalPo> list = approvalService.listWithTemplateList(approvalTemplateIdList);
        Map<Long, List<ApprovalTemplateSnapshotPo>> snapshotMap = getSnapshotMap(approvalTemplateIdList);
        Map<String, InstanceSnapshotDTO> instanceSnapshotMap = getInstanceSnapshot(approvalTemplateIdList);
        processData(snapshotMap, instanceSnapshotMap, list);
    }

    @Override
    public void incrementData(RefreshDataDTO refreshData) throws InterruptedException, ExecutionException {
        List<ApprovalPo> list = approvalService.listDataFromStartAndEnd(refreshData);
        List<Long> approvalTemplateIdList = list.stream().map(ApprovalPo::getApprovalTemplateId).distinct().collect(Collectors.toList());
        Map<Long, List<ApprovalTemplateSnapshotPo>> snapshotMap = getSnapshotMap(approvalTemplateIdList);
        Map<String, InstanceSnapshotDTO> instanceSnapshotMap = getInstanceSnapshot(approvalTemplateIdList);
        processData(snapshotMap, instanceSnapshotMap, list);
    }

    private void processData(Map<Long, List<ApprovalTemplateSnapshotPo>> snapshotMap, Map<String, InstanceSnapshotDTO> instanceSnapshotMap, List<ApprovalPo> list) throws InterruptedException, ExecutionException {
        if (CollectionUtils.isEmpty(list)) {
            log.info("没有数据需要初始化...");
            return;
        }

        List<ApprovalSnapshotPo> snapshots = list.parallelStream().map(e -> {
            Long approvalTemplateId = e.getApprovalTemplateId();

            List<ApprovalTemplateSnapshotPo> snapshotList = snapshotMap.get(approvalTemplateId);
            Map<Long, String> versionMap = snapshotList.stream().collect(Collectors.toMap(ApprovalTemplateSnapshotPo::getVersion, ApprovalTemplateSnapshotPo::getContent, (e1, e2) -> e2));
            String content = versionMap.get(e.getVersion());
            ApprovalSnapshotPo approvalSnapshotPo = new ApprovalSnapshotPo();
            approvalSnapshotPo.setApprovalId(e.getApprovalId());
            InstanceSnapshotDTO instanceSnapshot = instanceSnapshotMap.get(String.format("%s_%s", e.getApprovalTemplateId(), e.getVersion()));

            approvalSnapshotPo.setRelation(JSONObject.toJSONString(instanceSnapshot));
            approvalSnapshotPo.setApprovalTemplateSnapshot(content);
            return approvalSnapshotPo;
        }).collect(Collectors.toList());

        int batch = Math.min(snapshots.size(), 300);

        int core = (int)Math.ceil(snapshots.size() / (double)batch);

        ExecutorService executorService = SmartExecutorService.newFixedThreadPool();
        ExecutorCompletionService completeService = new ExecutorCompletionService(executorService);

        for (int i = 0; i < core; i++) {
            List<ApprovalSnapshotPo> approvalSnapshotPos =
                    snapshots.subList(i * batch, Math.min((i + 1) * batch, snapshots.size()));
            completeService.submit(() -> {
                approvalSnapshotPoService.saveBatch(approvalSnapshotPos);
                return null;
            });
        }

        for (int i = 0; i < core; i++) {
            Future<Void> take = completeService.take();
            take.get();
        }
        executorService.shutdown();
    }

    private Map<String, InstanceSnapshotDTO> getInstanceSnapshot(List<Long> approvalTemplateIdList) {

        List<ProcessRelatedPo> processRelatedList = processRelatedService.listProcessRelatedWithTemplate(approvalTemplateIdList);
        Map<Long, List<ProcessRelatedPo>> templateMap = processRelatedList.stream().collect(Collectors.groupingBy(ProcessRelatedPo::getApprovalTemplateId));


        Map<String, InstanceSnapshotDTO> instanceMap = new HashMap<>();
        templateMap.forEach((k, v) -> {
            Map<Long, List<ProcessRelatedPo>> versionMap = v.stream().collect(Collectors.groupingBy(ProcessRelatedPo::getVersion));

            versionMap.forEach((version, values) -> {
                InstanceSnapshotDTO instanceSnapshot = new InstanceSnapshotDTO();

                // 找到节点的属性关系
                Set<Long> node = new HashSet<>();
                values.forEach(o -> {
                    node.add(o.getProcessBeforeId());
                    node.add(o.getProcessAfterId());
                });

                List<ProcessPo> processPos = processService.listByIds(node);
                instanceSnapshot.setProcessList(processPos);
                instanceSnapshot.setProcessRelatedPoList(values);

                instanceMap.put(String.format("%s_%s", k, version), instanceSnapshot);
            });
        });
        return instanceMap;
    }

    private Map<Long, List<ApprovalTemplateSnapshotPo>> getSnapshotMap(List<Long> approvalTemplateIdList) {
        List<ApprovalTemplateSnapshotPo> approvalTemplates = approvalTemplateSnapshotService.listWithTemplateId(approvalTemplateIdList);
        return approvalTemplates.stream().collect(Collectors.groupingBy(ApprovalTemplateSnapshotPo::getApprovalTemplateId));
    }

    private Map<Long, List<TemplateVersionVO>> getTemplate(List<Long> templateIdList, Long sourceId,
        Map<Long, ProcessPo> processMap) {
        // 拆分出来模板,看那些模板中含有这些数据

        Map<Long, List<TemplateVersionVO>> templateVersionMap = new HashMap<>();

        Map<Long, List<ProcessRelatedPo>> relatedMap =
            processRelatedService.listProcessRelatedWithTemplate(templateIdList).stream()
                .collect(Collectors.groupingBy(ProcessRelatedPo::getApprovalTemplateId));
        relatedMap.forEach((k, v) -> {
            Map<Long, List<ProcessRelatedPo>> relatedInnerMap = v.stream().collect(Collectors.groupingBy(ProcessRelatedPo::getVersion));
            relatedInnerMap.forEach((k1, v1) -> {
                boolean match = v1.stream().anyMatch(e -> {
                    ProcessPo processPo = processMap.get(e.getProcessAfterId());
                    return Objects.equals(processPo.getAssociateGroupId(), sourceId.toString()) || processPo.isDynamic();
                });
                if (match) {
                    Long version = v1.get(0).getVersion();
                    // 进行收集
                    List<TemplateVersionVO> values = templateVersionMap.computeIfAbsent(k, o -> new ArrayList<>());
                    values.add(TemplateVersionVO.builder().version(version).relations(v1).build());
                    templateVersionMap.put(k, values);
                }
            });
        });
        return templateVersionMap;
    }

    @Data
    class Task implements Callable<DataTransferVO> {

        private Long templateId;
        private List<TemplateVersionVO> versionList;
        private Map<Long, ProcessPo> processMap;
        private ApprovalDataTransferDTO data;
        private Map<Long, ProcessPo> cache;
        private ApprovalDataTransferDTO.ApprovalDataTransferInternalDTO meta;


        public Task(Long templateId, List<TemplateVersionVO> versionList, ApprovalDataTransferDTO data, Map<Long, ProcessPo> processMap,  ApprovalDataTransferDTO.ApprovalDataTransferInternalDTO meta) {
            this.templateId = templateId;
            this.versionList = versionList;
            this.processMap = processMap;
            this.data = data;
            cache = new HashMap<>();
            this.meta = meta;
        }

        @Override
        public DataTransferVO call() {
            // 查询用户ID

            // 没有数据需要迁移

            DataTransferVO.DataTransferVOBuilder builder = DataTransferVO.builder();
            log.info("开始转移数据, 本次转移类型:{}", TransferTypeEnum.ofTransferType(data.getTransferType()));
            // 模板升级
            ApprovalTemplatePo approvalTemplatePo = approvalTemplateService.getById(templateId);

            if (Objects.equals(TransferTypeEnum.TEMPLATE.getCode(), data.getTransferType()) || Objects.equals(TransferTypeEnum.TEMPLATE_AND_DATA.getCode(), data.getTransferType())) {
                builder = upgrade(approvalTemplatePo);
            }

            // 数据
            if (Objects.equals(TransferTypeEnum.DATA.getCode(), data.getTransferType()) || Objects.equals(TransferTypeEnum.TEMPLATE_AND_DATA.getCode(), data.getTransferType())) {

                if (Objects.isNull(builder)) {
                    builder = DataTransferVO.builder();
                }

                List<ApprovalPo> approvalPos = approvalService.listApproving(templateId, Collections.emptyList(), meta.getApprovalIdList(), data.getStartDate(), data.getEndDate());
                // 审批数据
                List<Long> approvalIdList = approvalPos.stream().map(ApprovalPo::getApprovalId).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(approvalPos)) {
                    return builder.build();
                }

                List<ProcessDetailPo> processDetailList = processDetailService.listApproving(approvalIdList);
                // 节点数据
                List<Long> processDetailIdList = processDetailList.stream().map(ProcessDetailPo::getId).collect(Collectors.toList());

                // 审批详情数据
                Map<Long, ProcessDetailPo> detailMap = processDetailList.stream().collect(Collectors.toMap(ProcessDetailPo::getParentId, e -> e, (e1, e2) -> e2));
                // 审批实例数据
                Map<Long, List<ProcessInstanceApprovePo>> instanceMap = instanceApproveService.listByDetailIdList(processDetailIdList).stream().collect(Collectors.groupingBy(ProcessInstanceApprovePo::getApprovalId));
                // 审批快照数据
                Map<Long, ApprovalSnapshotPo> snapshotMap = approvalSnapshotPoService.listByApprovalId(approvalIdList).stream().collect(Collectors.toMap(ApprovalSnapshotPo::getApprovalId, e -> e, (e1, e2) -> e2));

                List<ProcessPo> saveProcessList = new ArrayList<>();
                List<ProcessDetailPo> saveProcessDetailList = new ArrayList<>();
                List<ApprovalPo> approvalPoList = new ArrayList<>();
                List<ProcessInstanceApprovePo> processInstanceApproveList = new ArrayList<>();
                List<ApprovalSnapshotPo> snapshotList = new ArrayList<>();
                List<TransferLogDetailPo> transferLogList = new ArrayList<>();

                for (ApprovalPo approval : approvalPos) {

                    List<ProcessInstanceApprovePo> processInstanceApproves = instanceMap.get(approval.getApprovalId());
                    ApprovalSnapshotPo approvalSnapshotPo = snapshotMap.get(approval.getApprovalId());
                    ProcessDetailPo processDetailPo = detailMap.get(approval.getApprovalId());
                    if (Objects.isNull(processDetailPo) || Objects.isNull(approvalSnapshotPo)) {
                        continue;
                    }

                    TransferLogDetailPo transferLogDetailPo = TransferLogDetailPo.ofDefault(approval, approvalTemplatePo);
//                    transferLogDetailPo.setBeforeRelation(approvalSnapshotPo.getRelation());

                    // 找找能不能找到sourceId
                    List<Long> nodes = NodeUtil.getNodes(approvalSnapshotPo.getRelation(), data.getSourceUserId());
                    Map<Long, Long> nodeMap = nodes.stream().collect(Collectors.toMap(e -> e, e -> e, (e1, e2) -> e2));

                    if (CollectionUtils.isEmpty(nodes)) {
                        // 说明找不到. 判断当前审批人中有没有sourceUserId. 部门负责人的情况
                        boolean contains = ConvertUtils.contains(approval.getUserId(), data.getSourceUserId());
                        if (!contains) {
                            // 不需要处理了.
                            continue;
                        }
                        boolean count = ConvertUtils.replace(approval, processInstanceApproves, data.getSourceUserId(), data.getTargetUserId(), data.getTargetUserName());
                        processDetailPo.updateSelf();
                        saveProcessDetailList.add(processDetailPo);
                        if (!count) {
                            // 未变化, 不需要处理
                            continue;
                        }
                        approvalPoList.add(approval);
                        processInstanceApproveList.addAll(processInstanceApproves);
//                        transferLogDetailPo.setTransferFlag(Boolean.TRUE);
                    } else {
                        // 判断是否过了节点. 过了节点的不需要替换
                        String relation = approvalSnapshotPo.getRelation();
                        InstanceSnapshotDTO instanceSnapshot = JSONObject.parseObject(relation, InstanceSnapshotDTO.class);
                        List<ProcessRelatedPo> processRelates = instanceSnapshot.getProcessRelatedPoList();
                        // 下一个节点
                        ProcessPo processPo = null;
                        Map<Long, ProcessPo> processMaps = instanceSnapshot.ofProcessMap();
                        if (processDetailPo.isSpecialNode() ) {
                            // 找到真实替换的那个
                            Long processId = processDetailPo.getProcessId();
                            for (ProcessRelatedPo related : processRelates) {
                                ProcessPo p = processMaps.get(related.getProcessAfterId());
                                if (Objects.equals(related.getProcessBeforeId(), processId) && Objects.equals(data.getSourceUserId().toString(), p.getAssociateGroupId())) {
                                    processPo = p;
                                }
                            }
                        } else {
                            // in case 空指针
                            processPo = processMaps.get(processDetailPo.getNextProcessId());
                        }

                        for (ProcessRelatedPo related : processRelates) {

                            // 提前找到了节点, 说明该节点
                            if (Objects.nonNull(processPo) && Objects.equals(related.getProcessAfterId(), processPo.getId())) {
                                break;
                            }
                            nodeMap.remove(related.getProcessAfterId());
                            nodes = new ArrayList<>(nodeMap.values());
                        }
                        if (CollectionUtils.isEmpty(nodes)) {
                            // 说明都过了.不需要替换了
                            continue;
                        }
                        // TODO 说明可以找到节点
                        boolean contains = ConvertUtils.contains(approval.getUserId(), data.getSourceUserId());
                        if (contains) {
                            // 需要判断是属于部门负责人还是普通节点
                            // 或签节点
                            if (processDetailPo.isSharedApproval()) {
                                boolean replace = ConvertUtils.replace(approval, processInstanceApproves, data.getSourceUserId(), data.getTargetUserId(), data.getTargetUserName());
                                if (!replace) {
                                    // 不需要处理
                                    continue;
                                }
                                ConvertUtils.replace(approvalSnapshotPo, nodeMap, data.getTargetUserId(), data.getTargetUserName());
                                approvalPoList.add(approval);
                                processInstanceApproveList.addAll(processInstanceApproves);
                                snapshotList.add(approvalSnapshotPo);
                            } else if (processPo.isDynamic()) {
                                ConvertUtils.replace(approvalSnapshotPo, nodeMap, data.getTargetUserId(), data.getTargetUserName());
                                ConvertUtils.replace(approval, data.getSourceUserId(), data.getTargetUserId(), data.getTargetUserName());
                                boolean replace = ConvertUtils.replace(approval, processInstanceApproves, data.getSourceUserId(), data.getTargetUserId(), data.getTargetUserName());
                                if (!replace) {
                                    continue;
                                }
                                snapshotList.add(approvalSnapshotPo);
                                approvalPoList.add(approval);
                                processInstanceApproveList.addAll(processInstanceApproves);
                            } else {
                                ConvertUtils.replace(approval, data.getSourceUserId(), data.getTargetUserId(), data.getTargetUserName());
                                boolean replace = ConvertUtils.replace(approval, processInstanceApproves, data.getSourceUserId(), data.getTargetUserId(), data.getTargetUserName());
                                if (!replace) {
                                    continue;
                                }
                                ConvertUtils.replace(approvalSnapshotPo, nodeMap, data.getTargetUserId(), data.getTargetUserName());
                                ConvertUtils.replace(processDetailPo, cache);

                                approvalPoList.add(approval);
                                processInstanceApproveList.addAll(processInstanceApproves);
                                snapshotList.add(approvalSnapshotPo);
                            }
//                            transferLogDetailPo.setTransferFlag(Boolean.TRUE);
                            processDetailPo.updateSelf();
                            saveProcessDetailList.add(processDetailPo);
                        } else {
                            // 不包含却能找到,说明替换节点在后面. 需要进行替换
                            ConvertUtils.replace(approvalSnapshotPo, nodeMap, data.getTargetUserId(), data.getTargetUserName());
                            snapshotList.add(approvalSnapshotPo);
                        }

                        // 记录日志详情
                        approvalSnapshotPo.updateSelf();
//                        transferLogDetailPo.setAfterRelation(approvalSnapshotPo.getRelation());
                        transferLogList.add(transferLogDetailPo);
                    }
                }

                DataTransferVO build = builder.processDetailList(saveProcessDetailList).approvalPoList(approvalPoList)
                        .processInstanceApproveList(processInstanceApproveList).snapshotList(snapshotList)
                        .transferLogList(transferLogList).build();

                List<ProcessPo> processList = build.getSaveProcessList();
                if (!CollectionUtils.isEmpty(processList)) {
                    saveProcessList.addAll(processList);
                }
                build.setSaveProcessList(saveProcessList);
                return build;
            }

            if (Objects.isNull(builder)) {
                return null;
            }

            return builder.build();
        }

        private DataTransferVO.DataTransferVOBuilder upgrade(ApprovalTemplatePo approvalTemplatePo) {
            // 升级模板
            List<ProcessRelatedPo> processRelatedPos = processRelatedService.listProcessRelatedAfterProcessId(templateId, approvalTemplatePo.getVersion(), null);
            log.info("【{}】开始查询替换的节点", approvalTemplatePo.getTitle());

            List<Long> nodes = NodeUtil.getNodes(processMap, JSONObject.toJSONString(processRelatedPos), data.getSourceUserId());
            log.info("【{}】查询替换的节点结果, {}", approvalTemplatePo.getTitle(), JSONObject.toJSON(nodes));
            List<ProcessPo> processList = new ArrayList<>();
            // 升级目前快照的数据
            ApprovalTemplateSnapshotPo snapshot = approvalTemplateSnapshotService.getById(approvalTemplatePo.getApprovalSnapshotId());
            List<Long> relatedIdList = processRelatedPos.stream().map(BaseEntity::getId).collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(nodes)) {
                // 找到对应relation关系.
                Map<Long, List<ProcessRelatedAttribute>> relatedMap = processRelatedAttributeService.listByRelatedId(relatedIdList).stream().collect(Collectors.groupingBy(ProcessRelatedAttribute::getRelatedId));

                List<ProcessRelatedAttribute> addMoreRelationAttributes = new ArrayList<>();
                log.info("开始查询模板:{}, 版本:{} 对应的节点属性关系", approvalTemplatePo.getTitle(), approvalTemplatePo.getVersion());
                List<ProcessFormNodeRelation> processFormRelations = processFormNodeRelationService.listAttributes(templateId, approvalTemplatePo.getVersion());
                log.info("查询模板:{}, 版本:{} 对应的节点属性关系, 结果:{}", approvalTemplatePo.getTitle(), approvalTemplatePo.getVersion(), JSONObject.toJSONString(processFormRelations));

                TemplateConfigPo templateConfigPo = templateConfigService.getByTemplateId(templateId, approvalTemplatePo.getVersion());

                // 开始升级
                approvalTemplatePo.setVersion(approvalTemplatePo.getVersion() + 1);
                templateConfigPo.setVersion(approvalTemplatePo.getVersion());
                // 设置id为自增参数
                templateConfigPo.setId(null);
                // 需要把对应单的数据也进行升级

                List<ProcessRelatedPo> relationList = processRelatedPos.stream().map(e -> {
                    ProcessRelatedPo processRelatedPo = e.cloneProcessRelatedPo();
                    processRelatedPo.setCreateTime(new Date());
                    processRelatedPo.setId(UuidUtil.generateId());
                    processRelatedPo.setVersion(approvalTemplatePo.getVersion());
                    ProcessPo processPo = nodes.contains(processRelatedPo.getProcessAfterId()) ? processMap.get(processRelatedPo.getProcessAfterId()) : null;
                    ProcessPo beforeProcess = nodes.contains(processRelatedPo.getProcessBeforeId()) ? processMap.get(processRelatedPo.getProcessBeforeId()) : null;

                    // 同时检查是否已经有对应的数据, 有对应的数据直接替换关联关系即可

                    if (Objects.nonNull(processPo)) {
                        ProcessPo p = cache.get(processPo.getId());
                        if (Objects.isNull(p)) {
                            // 直接获取
                            ProcessPo cloneProcess = processPo.cloneProcess();
                            cloneProcess.setId(UuidUtil.generateId());
                            cloneProcess.setAssociateGroupId(data.getTargetUserId().toString());
                            cloneProcess.setAssociateGroupName(data.getTargetUserName());
                            processRelatedPo.setProcessAfterId(cloneProcess.getId());
                            processList.add(cloneProcess);

                            processFormRelations.forEach(o -> {
                                if (Objects.equals(o.getProcessId(), processPo.getId())) {
                                    o.setProcessId(cloneProcess.getId());
                                }
                                o.setId(UuidUtil.generateId());
                                o.setVersion(approvalTemplatePo.getVersion());
                            });
                            cache.put(processPo.getId(), cloneProcess);
                        } else {
                            processRelatedPo.setProcessAfterId(p.getId());
                        }
                    }

                    if (Objects.nonNull(beforeProcess)) {
                        ProcessPo p = cache.get(beforeProcess.getId());

                        if (Objects.isNull(p)) {
                            // 直接获取
                            ProcessPo cloneProcess = beforeProcess.cloneProcess();
                            cloneProcess.setId(UuidUtil.generateId());
                            cloneProcess.setAssociateGroupId(data.getTargetUserId().toString());
                            cloneProcess.setAssociateGroupName(data.getTargetUserName());
                            processRelatedPo.setProcessBeforeId(cloneProcess.getId());

                            processFormRelations.forEach(o -> {
                                if (Objects.equals(o.getProcessId(), beforeProcess.getId())) {
                                    o.setProcessId(cloneProcess.getId());
                                }
                                o.setId(UuidUtil.generateId());
                                o.setVersion(approvalTemplatePo.getVersion());
                            });

                            processList.add(cloneProcess);
                            cache.put(beforeProcess.getId(), cloneProcess);
                        } else {
                            processRelatedPo.setProcessBeforeId(p.getId());
                        }
                    }
                    List<ProcessRelatedAttribute> processRelatedAttributes = relatedMap.get(e.getId());
                    if (!CollectionUtils.isEmpty(processRelatedAttributes)) {
                        List<ProcessRelatedAttribute> newRelationAttributes = processRelatedAttributes.stream().peek(o -> {
                            o.setRelatedId(processRelatedPo.getId());
                            o.setVersion(processRelatedPo.getVersion());
//                            o.setGroupId(processRelatedPo.getGroupId());
                            o.setId(UuidUtil.generateId());
                        }).collect(Collectors.toList());
                        addMoreRelationAttributes.addAll(newRelationAttributes);
                    }
                    return processRelatedPo;
                }).collect(Collectors.toList());

                // 新建一个快照数据
                ApprovalTemplateSnapshotPo approvalTemplateSnapshotPo = buildNewSnapshot(snapshot, data);
                approvalTemplatePo.setApprovalSnapshotId(approvalTemplateSnapshotPo.getId());
                return DataTransferVO.builder()
                        .saveProcessList(processList)
                        .relatedProcessList(relationList)
                        .addMoreRelationAttributes(addMoreRelationAttributes)
                        .processFormNodeRelations(processFormRelations)
                        .approvalTemplatePo(approvalTemplatePo)
                        .templateConfigPo(templateConfigPo)
                        .approvalTemplateSnapshotPo(approvalTemplateSnapshotPo);
            }
            return null;
        }
    }

    private ApprovalTemplateSnapshotPo buildNewSnapshot(ApprovalTemplateSnapshotPo snapshot, ApprovalDataTransferDTO data) {
        ApprovalTemplateSnapshotPo newVersion = snapshot.copy();
        newVersion.setId(UuidUtil.generateId());
        // 解析参数,
        ApprovalTemplateDTO approvalTemplateDTO = JSONObject.parseObject(snapshot.getContent(), ApprovalTemplateDTO.class);
        JSONObject jsonObject = JSONObject.parseObject(snapshot.getContent(), JSONObject.class);
        List<ApprovalTemplateDTO.NodeData> nodeDataArray = approvalTemplateDTO.getNodeDataArray();
        for (ApprovalTemplateDTO.NodeData node : nodeDataArray) {
            List<ApprovalTemplateDTO.Audit> auditList = node.getAuditList();
            for (ApprovalTemplateDTO.Audit audit : auditList) {
                if (Objects.equals(audit.getUserId(), data.getSourceUserId().toString())) {
                    audit.setUserId(data.getTargetUserId().toString());
                    audit.setUserName(data.getTargetUserName());
                }
            }
        }
        jsonObject.put("nodeDataArray", nodeDataArray);
        newVersion.setContent(JSONObject.toJSONString(jsonObject));
        newVersion.setVersion(newVersion.getVersion() + 1);

        // 设置审批人
        List<String> arrays = JSONObject.parseArray(newVersion.getApprovalName(), String.class);
        for (int i = 0; i < arrays.size(); i++) {
            if (StringUtils.equals(arrays.get(i), data.getSourceUserName())) {
                arrays.set(i, data.getTargetUserName());
            }
        }
        newVersion.setApprovalName(JSONObject.toJSONString(arrays));
        return newVersion;
    }

}
